// SQFunction.h: interface for the SQFunction class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SQFUNCTION_H__0A8840CC_3632_4286_B67D_C4767C7269E3__INCLUDED_)
#define AFX_SQFUNCTION_H__0A8840CC_3632_4286_B67D_C4767C7269E3__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


#ifndef _X_SQFunction_H_
#define _X_SQFunction_H_
#include <squirrel.h> 
#include <assert.h>

#include "../squirrel/sqmem.cpp"
/* It seems that I should included sqstate.h for sq_vm_free declaration which is used in sqvm.h in the macro sq_delete
, but if I include sqstate.h ,error c2660 will be given in VC6 ,for 'new' : function does not take 2 parameters */
//#include <sqstate.h>//error C2660: 'new' : function does not take 2 parameters
#include <../squirrel/sqvm.h>
#include <string.h>
#include <../squirrel/sqstring.h>
#include <../squirrel/sqarray.h>
#include <../squirrel/sqtable.h>
float globlefloatbuf[16];
double globledoublebuf[16];
SQChar* globlestrbuf[10];
#ifdef SQUNICODE
#define scstrcpy strcpy
#else
#define scstrcpy wcscpy 
#endif
#define SQFUNCTION_PRECALL() RT ret = RT(-1);\
SQInteger top = sq_gettop(m_vm); \
sq_pushroottable(m_vm); \
sq_pushstring(m_vm,_SC(m_strfunctionName),-1);\
if(SQ_SUCCEEDED(sq_get(m_vm,-2))) { \
sq_pushroottable(m_vm); 

#define SQFUNCTION_POSTCALL(numArgs)	sq_call(m_vm,numArgs+1,SQTrue,SQTrue);\
										ret = static_cast<RT>(SqTypeWrapper(stack_get(m_vm, -1)));\
										}\
										sq_settop(m_vm,top); \
										return ret;
#define SQFUNCTIONVOID_PRECALL() \
								SQInteger top = sq_gettop(m_vm); \
								sq_pushroottable(m_vm); \
								sq_pushstring(m_vm,_SC(m_strfunctionName),-1);\
								if(SQ_SUCCEEDED(sq_get(m_vm,-2))) { \
								sq_pushroottable(m_vm); 

#define SQFUNCTIONVOID_POSTCALL(numArgs)	sq_call(m_vm,numArgs+1,SQFalse,SQTrue);}\
											sq_settop(m_vm,top); 

SQInteger register_global_func(HSQUIRRELVM v,SQFUNCTION f,const char *fname)
{
	sq_pushroottable(v);
	sq_pushstring(v,fname,-1);
	sq_newclosure(v,f,0); //create a new function
	sq_createslot(v,-3); 
	sq_pop(v,1); //pops the root table 
	return 1;
}

struct SqTypeWrapper
{
	const SQObjectPtr & sqobj;
	SqTypeWrapper(const SQObjectPtr &o):sqobj(o)
	{
	//	sqobj = &o;
	};
	SqTypeWrapper(SqTypeWrapper *clonee):sqobj(clonee->sqobj)
	{
		//	sqobj = &o;
	};
	operator int()
	{
		return sqobj._unVal.nInteger;
	}
	operator unsigned int()
	{
		return sqobj._unVal.nInteger;
	}
	operator  float*()
	{
		switch (sqobj._type)
		{
		case OT_ARRAY:
			{
				SQArray* parray = sqobj._unVal.pArray;
				for(int i = 0;i<parray->_values.size();i++)
				{
					SQObjectPtr temp;
					parray->Get(i,temp);
					globlefloatbuf[i] = (float) temp._unVal.fFloat;
				}
				return globlefloatbuf;
			}
// 		case OT_TABLE:
// 			{
// 				SQTable* pTable =  sqobj._unVal.pTable;
// 				for (int i = 0;i<pTable->CountUsed();i++)
// 				{
// 					SQObjectPtr tmp;
// 					pTable->_Get(tmp,i);
// 
// 				}
// 				return globlefloatbuf;
// 			}

		}
		SQArray* parray = sqobj._unVal.pArray;
		for(int i = 0;i<parray->_values.size();i++)
		{
			SQObjectPtr temp;
			parray->Get(i,temp);
			globlefloatbuf[i] =  SqTypeWrapper(temp);
		}
		return globlefloatbuf;
	}
	operator  double*()
	{
		SQArray* parray = sqobj._unVal.pArray;
		for(int i = 0;i<parray->_values.size();i++)
		{
			SQObjectPtr temp;
			parray->Get(i,temp);
			globledoublebuf[i] = SqTypeWrapper(temp);
		}
		return globledoublebuf;
	}
	operator SQChar*()
	{
		SQString* sqstr = sqobj._unVal.pString;
		return sqstr->_val;
	}
	operator SQChar**()
	{
		SQString* sqstr = sqobj._unVal.pString;
		globlestrbuf[0] = sqstr->_val;
		return globlestrbuf;
	}
	operator float()
	{
		switch(sqobj._type)
		{
		case  OT_INTEGER:
			{
				return  static_cast<int>(sqobj._unVal.nInteger);
			}
		}
		return sqobj._unVal.fFloat;
	}
	operator double()
	{		
		switch(sqobj._type)
		{
			case  OT_INTEGER:
			{
			return  static_cast<int>(sqobj._unVal.nInteger);
			}
		}
		return sqobj._unVal.fFloat;
	}
};
template <typename T1>
void Push(HSQUIRRELVM v,T1 p1)
{
	v->Push(p1);
}
template <>
void Push(HSQUIRRELVM v,unsigned int p1)
{
	v->Push((int)p1);
}
void Push(HSQUIRRELVM v,SQChar* p1)
{
	v->Push(SQString::Create(_ss(v),p1));
}
template<class T> struct TypeWrapper {};

template <class T>
T Get(TypeWrapper<T>,HSQUIRRELVM v,SQInteger index)
{
	return static_cast<T>(SqTypeWrapper(stack_get(v, index)));
}


template <typename RT>
class SqFunction
{
public:
	SqFunction()
	{

	}
	SqFunction(HSQUIRRELVM v,const SQChar* functionName):m_vm(v)
	{
	m_strfunctionName = functionName;
	}

	template <typename T1>
	RT operator()(T1 p1)
	{
	SQFUNCTION_PRECALL()
	Push(p1);
	SQFUNCTION_POSTCALL(1)
	}
	template <typename T1,typename T2>
	RT operator()(T1 p1,T2 p2)
	{
	SQFUNCTION_PRECALL()
	Push(p1);
	Push(p2);
	SQFUNCTION_POSTCALL(2)
	}
	template <typename T1,typename T2,typename T3>
	RT operator()(T1 p1,T2 p2,T3 p3)
	{
	SQFUNCTION_PRECALL()
	Push(p1);
	Push(p2);
	Push(p3);
	SQFUNCTION_POSTCALL(3)
	}
	template <typename T1,typename T2,typename T3,typename T4>
	RT operator()(T1 p1,T2 p2,T3 p3,T4 p4)
	{
		SQFUNCTION_PRECALL()
		Push(p1);
		Push(p2);
		Push(p3);
		Push(p4);
		SQFUNCTION_POSTCALL(4)
	}
	RT operator()()
	{
	SQFUNCTION_PRECALL()
	SQFUNCTION_POSTCALL(0)
	}
	template <typename T1>
	void Push(T1 p1)
	{
	m_vm->Push(p1);
	}
	template <>
	void Push<const SQChar*>(const SQChar* p1)
	{
		m_vm->Push(SQString::Create(_ss(m_vm),p1));
	}
	template <>
	void Push<SQChar*>(SQChar* p1)
	{
		m_vm->Push(SQString::Create(_ss(m_vm),p1));
	}
	protected:
	HSQUIRRELVM m_vm; 
	const SQChar* m_strfunctionName;
};
template <>
class SqFunction<void>{
public:
	SqFunction()
	{

	}
	SqFunction(HSQUIRRELVM v,const char* functionName):m_vm(v)
	{
	m_strfunctionName = functionName;
	}

	template <typename T1>
	void operator()(T1 p1)
	{
	SQFUNCTIONVOID_PRECALL()
	Push(p1);
	SQFUNCTIONVOID_POSTCALL(1)
	}
	template <typename T1,typename T2>
	void operator()(T1 p1,T2 p2)
	{
	SQFUNCTIONVOID_PRECALL()
	Push(p1);
	Push(p2);
	SQFUNCTIONVOID_POSTCALL(2)
	}
	template <typename T1,typename T2,typename T3>
	void operator()(T1 p1,T2 p2,T3 p3)
	{
	SQFUNCTIONVOID_PRECALL()
	Push(p1);
	Push(p2);
	Push(p3);
	SQFUNCTIONVOID_POSTCALL(3)
	}
	template <typename T1,typename T2,typename T3,typename T4>
	void operator()(T1 p1,T2 p2,T3 p3,T4 p4)
	{
		SQFUNCTIONVOID_PRECALL()
		Push(p1);
		Push(p2);
		Push(p3);
		Push(p4);
		SQFUNCTIONVOID_POSTCALL(4)
	}
	void operator()()
	{
	SQFUNCTIONVOID_PRECALL()
	SQFUNCTIONVOID_POSTCALL(0)
	}
	template <typename T1>
	void Push(T1 p1)
	{
		m_vm->Push(p1);
	}
	template <>
	void Push<const SQChar*>(const SQChar* p1)
	{
		m_vm->Push(SQString::Create(_ss(m_vm),p1));
	}
	template <>
	void Push<SQChar*>(SQChar* p1)
	{
		m_vm->Push(SQString::Create(_ss(m_vm),p1));
	}
	protected:
	HSQUIRRELVM m_vm;

	const SQChar* m_strfunctionName;

};
#endif


struct StackHandler {
  StackHandler(HSQUIRRELVM v) {
    _top = sq_gettop(v);
    this->v = v;
  }
  SQFloat GetFloat(int idx) {
    SQFloat x = 0.0f;
    if(idx > 0 && idx <= _top) {
      sq_getfloat(v,idx,&x);
    }
    return x;
  }
  SQInteger GetInt(int idx) {
    SQInteger x = 0;
    if(idx > 0 && idx <= _top) {
      sq_getinteger(v,idx,&x);
    }
    return x;
  }
  HSQOBJECT GetObjectHandle(int idx) {
    HSQOBJECT x;
    if(idx > 0 && idx <= _top) {
      sq_resetobject(&x);
      sq_getstackobj(v,idx,&x);
    }
    return x;
  }
  const SQChar *GetString(int idx)
  {
    const SQChar *x = NULL;
    if(idx > 0 && idx <= _top) {
      sq_getstring(v,idx,&x);
    }
    return x;
  }
  SQUserPointer GetUserPointer(int idx)
  {
    SQUserPointer x = 0;
    if(idx > 0 && idx <= _top) {
      sq_getuserpointer(v,idx,&x);
    }
    return x;
  }
  SQUserPointer GetInstanceUp(int idx,SQUserPointer tag)
  {
    SQUserPointer self;
    if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&self,tag)))
      return NULL;
    return self;
  }
  SQUserPointer GetUserData(int idx,SQUserPointer tag=0)
  {
    SQUserPointer otag;
    SQUserPointer up;
    if(idx > 0 && idx <= _top) {
      if(SQ_SUCCEEDED(sq_getuserdata(v,idx,&up,&otag))) {
        if(tag == otag)
          return up;
      }
    }
    return NULL;
  }

  int GetType(int idx)
  {
    if(idx > 0 && idx <= _top) {
      return sq_gettype(v,idx);
    }
    return -1;
  }
  
  int GetParamCount() {
    return _top;
  }
  int Return(const SQChar *s)
  {
    sq_pushstring(v,s,-1);
    return 1;
  }
  int Return(float f)
  {
    sq_pushfloat(v,f);
    return 1;
  }
  int Return(int i)
  {
    sq_pushinteger(v,i);
    return 1;
	}
	int Return(bool b)
	{
		sq_pushbool(v,b);
		return 1;
	}
  int Return(SQUserPointer p) {
    sq_pushuserpointer(v,p);
    return 1;
  }

	int Return() { return 0; }
	bool GetBool(int idx)
	{
		SQBool ret;
		if(idx > 0 && idx <= _top) {
			if(SQ_SUCCEEDED(sq_getbool(v,idx,&ret)))
				return ret;
		}
		return false;
  }
  HSQUIRRELVM GetVMPtr() { return v; }
private:
	int _top;
	HSQUIRRELVM v;
};



template<class RT>
struct ReturnSpecialization {
	template <typename Callee>
		static int Callx(Callee & callee,RT(Callee::*func)() ,HSQUIRRELVM v,int index) {
		RT ret = (callee.*func)();
		Push(v,ret);
		return 1;
  }
  // === Standard Function calls ===
  static int Call(RT (*func)(),HSQUIRRELVM v,int /*index*/) {
    RT ret = func();
	Push(v,ret);
    return 1;
  }
  static int Call(RT (__stdcall*func)(),HSQUIRRELVM v,int /*index*/) {
	  RT ret = func();
	  Push(v,ret);
	  return 1;
  }
  template<typename P1>
  static int Call(RT (*func)(P1),HSQUIRRELVM v,int index) {
    RT ret = func(
      Get(TypeWrapper<P1>(),v,index + 0)
    );
    Push(v,ret);
    return 1;
  }
  template<typename P1>
  static int Call(RT (__stdcall*func)(P1),HSQUIRRELVM v,int index) {
	  RT ret = func(
		  Get(TypeWrapper<P1>(),v,index + 0)
		  );
	  Push(v,ret);
	  return 1;
  }
  template<typename P1,typename P2>
  static int Call(RT (*func)(P1,P2),HSQUIRRELVM v,int index) {
    RT ret = func(
      Get(TypeWrapper<P1>(),v,index + 0),
      Get(TypeWrapper<P2>(),v,index + 1)
    );
    Push(v,ret);
    return 1;
  }
  template<typename P1,typename P2>
  static int Call(RT (__stdcall*func)(P1,P2),HSQUIRRELVM v,int index) {
	  RT ret = func(
		  Get(TypeWrapper<P1>(),v,index + 0),
		  Get(TypeWrapper<P2>(),v,index + 1)
		  );
	  Push(v,ret);
	  return 1;
  }
  template<typename P1,typename P2,typename P3>
  static int Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,int index) {
    RT ret = func(
      Get(TypeWrapper<P1>(),v,index + 0),
      Get(TypeWrapper<P2>(),v,index + 1),
      Get(TypeWrapper<P3>(),v,index + 2)
    );
    Push(v,ret);
    return 1;
  }

  template<typename P1,typename P2,typename P3>
  static int Call(RT (__stdcall*func)(P1,P2,P3),HSQUIRRELVM v,int index) {
	  RT ret = func(
		  Get(TypeWrapper<P1>(),v,index + 0),
		  Get(TypeWrapper<P2>(),v,index + 1),
		  Get(TypeWrapper<P3>(),v,index + 2)
		  );
	  Push(v,ret);
	  return 1;
  } 
  template<typename P1,typename P2,typename P3,typename P4>
  static int Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {
    RT ret = func(
      Get(TypeWrapper<P1>(),v,index + 0),
      Get(TypeWrapper<P2>(),v,index + 1),
      Get(TypeWrapper<P3>(),v,index + 2),
      Get(TypeWrapper<P4>(),v,index + 3)
    );
    Push(v,ret);
    return 1;
  }
  template<typename P1,typename P2,typename P3,typename P4>
  static int Call(RT (__stdcall*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {
	  RT ret = func(
		  Get(TypeWrapper<P1>(),v,index + 0),
		  Get(TypeWrapper<P2>(),v,index + 1),
		  Get(TypeWrapper<P3>(),v,index + 2),
		  Get(TypeWrapper<P4>(),v,index + 3)
		  );
	  Push(v,ret);
	  return 1;
  }
  template<typename P1,typename P2,typename P3,typename P4,typename P5>
  static int Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {
	  RT ret = func(
		  Get(TypeWrapper<P1>(),v,index + 0),
		  Get(TypeWrapper<P2>(),v,index + 1),
		  Get(TypeWrapper<P3>(),v,index + 2),
		  Get(TypeWrapper<P4>(),v,index + 3),
		  Get(TypeWrapper<P5>(),v,index + 4)
		  );
	  Push(v,ret);
	  return 1;
  }
  template<typename P1,typename P2,typename P3,typename P4,typename P5>
  static int Call(RT (__stdcall *func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {
	  RT ret = func(
		  Get(TypeWrapper<P1>(),v,index + 0),
		  Get(TypeWrapper<P2>(),v,index + 1),
		  Get(TypeWrapper<P3>(),v,index + 2),
		  Get(TypeWrapper<P4>(),v,index + 3),
		  Get(TypeWrapper<P5>(),v,index + 4)
		  );
	  Push(v,ret);
	  return 1;
  }


  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
  static int Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {
    RT ret = func(
      Get(TypeWrapper<P1>(),v,index + 0),
      Get(TypeWrapper<P2>(),v,index + 1),
      Get(TypeWrapper<P3>(),v,index + 2),
      Get(TypeWrapper<P4>(),v,index + 3),
      Get(TypeWrapper<P5>(),v,index + 4),
      Get(TypeWrapper<P6>(),v,index + 5)
    );
    Push(v,ret);
    return 1;
  }
  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
  static int Call(RT (__stdcall*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {
	  RT ret = func(
		  Get(TypeWrapper<P1>(),v,index + 0),
		  Get(TypeWrapper<P2>(),v,index + 1),
		  Get(TypeWrapper<P3>(),v,index + 2),
		  Get(TypeWrapper<P4>(),v,index + 3),
		  Get(TypeWrapper<P5>(),v,index + 4),
		  Get(TypeWrapper<P6>(),v,index + 5)
		  );
	  Push(v,ret);
	  return 1;
  }
  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
  static int Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
    RT ret = func(
      Get(TypeWrapper<P1>(),v,index + 0),
      Get(TypeWrapper<P2>(),v,index + 1),
      Get(TypeWrapper<P3>(),v,index + 2),
      Get(TypeWrapper<P4>(),v,index + 3),
      Get(TypeWrapper<P5>(),v,index + 4),
      Get(TypeWrapper<P6>(),v,index + 5),
      Get(TypeWrapper<P7>(),v,index + 6)
    );
    Push(v,ret);
    return 1;
  }
 

  template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
  static int Call(RT (__stdcall*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
	  RT ret = func(
		  Get(TypeWrapper<P1>(),v,index + 0),
		  Get(TypeWrapper<P2>(),v,index + 1),
		  Get(TypeWrapper<P3>(),v,index + 2),
		  Get(TypeWrapper<P4>(),v,index + 3),
		  Get(TypeWrapper<P5>(),v,index + 4),
		  Get(TypeWrapper<P6>(),v,index + 5),
		  Get(TypeWrapper<P7>(),v,index + 6)
		  );
	  Push(v,ret);
	  return 1;
  }



};

template<>
struct ReturnSpecialization<void> {
	template<typename Callee>
	static int Call(Callee & callee,void ( Callee::*func)() , HSQUIRRELVM,int /*index*/) {
		(callee.*func)();
		return 0;
	}
	// === Standard function calls ===

	static int Call(void (*func)(),HSQUIRRELVM v,int /*index*/) {
		(void)v;
		func();
		return 0;
	}
	static int Call(void (__stdcall*func)(),HSQUIRRELVM v,int /*index*/) {
		(void)v;
		func();
		return 0;
	}
	template<typename P1>
		static int Call(void (*func)(P1),HSQUIRRELVM v,int index) {
		func(
			Get(TypeWrapper<P1>(),v,index + 0)
			);
		return 0;
	}
		template<typename P1>
		static int Call(void (__stdcall*func)(P1),HSQUIRRELVM v,int index) {
			func(
				Get(TypeWrapper<P1>(),v,index + 0)
				);
			return 0;
		}	
	template<typename P1,typename P2>
		static int Call(void (*func)(P1,P2),HSQUIRRELVM v,int index) {
		func(
			Get(TypeWrapper<P1>(),v,index + 0),
			Get(TypeWrapper<P2>(),v,index + 1)
			);
		return 0;
	}
		template<typename P1,typename P2>
		static int Call(void (__stdcall*func)(P1,P2),HSQUIRRELVM v,int index) {
			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1)
				);
			return 0;
		}	
	template<typename P1,typename P2,typename P3>
		static int Call(void (*func)(P1,P2,P3),HSQUIRRELVM v,int index) {
		func(
			Get(TypeWrapper<P1>(),v,index + 0),
			Get(TypeWrapper<P2>(),v,index + 1),
			Get(TypeWrapper<P3>(),v,index + 2)
			);
		return 0;
	}
		template<typename P1,typename P2,typename P3>
		static int Call(void (__stdcall *func)(P1,P2,P3),HSQUIRRELVM v,int index) {
			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2)
				);
			return 0;
		}
	template<typename P1,typename P2,typename P3,typename P4>
		static int Call(void (*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {
		
		func(
			Get(TypeWrapper<P1>(),v,index + 0),
			Get(TypeWrapper<P2>(),v,index + 1),
			Get(TypeWrapper<P3>(),v,index + 2),
			Get(TypeWrapper<P4>(),v,index + 3)
			);
		return 0;
	}
		template<typename P1,typename P2,typename P3,typename P4>
		static int Call(void (__stdcall*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {

			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3)
				);
			return 0;
		}
		template<typename P1,typename P2,typename P3,typename P4,typename P5>
		static int Call(void (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {

			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3),
				Get(TypeWrapper<P5>(),v,index + 4)
				);
			return 0;
		}
		template<typename P1,typename P2,typename P3,typename P4,typename P5>
		static int Call(void (__stdcall*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {

			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3),
				Get(TypeWrapper<P5>(),v,index + 4)
				);
			return 0;
		}
	template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
		static int Call(void (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {
		
		func(
			Get(TypeWrapper<P1>(),v,index + 0),
			Get(TypeWrapper<P2>(),v,index + 1),
			Get(TypeWrapper<P3>(),v,index + 2),
			Get(TypeWrapper<P4>(),v,index + 3),
			Get(TypeWrapper<P5>(),v,index + 4),
			Get(TypeWrapper<P6>(),v,index + 5)
			);
		return 0;
	}
		template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
		static int Call(void (__stdcall*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {

			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3),
				Get(TypeWrapper<P5>(),v,index + 4),
				Get(TypeWrapper<P6>(),v,index + 5)
				);
			return 0;
		}
	template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
		static int Call(void (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
		func(
			Get(TypeWrapper<P1>(),v,index + 0),
			Get(TypeWrapper<P2>(),v,index + 1),
			Get(TypeWrapper<P3>(),v,index + 2),
			Get(TypeWrapper<P4>(),v,index + 3),
			Get(TypeWrapper<P5>(),v,index + 4),
			Get(TypeWrapper<P6>(),v,index + 5),
			Get(TypeWrapper<P7>(),v,index + 6)
			);
		return 0;
  }
		template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
		static int Call(void (__stdcall*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3),
				Get(TypeWrapper<P5>(),v,index + 4),
				Get(TypeWrapper<P6>(),v,index + 5),
				Get(TypeWrapper<P7>(),v,index + 6)
				);
			return 0;
		}
		template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8>
		static int Call(void (*func)(P1,P2,P3,P4,P5,P6,P7,P8),HSQUIRRELVM v,int index) {
			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3),
				Get(TypeWrapper<P5>(),v,index + 4),
				Get(TypeWrapper<P6>(),v,index + 5),
				Get(TypeWrapper<P7>(),v,index + 6),
				Get(TypeWrapper<P8>(),v,index + 7)
				);
			return 0;
		}
		template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8>
		static int Call(void (__stdcall*func)(P1,P2,P3,P4,P5,P6,P7,P8),HSQUIRRELVM v,int index) {
			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3),
				Get(TypeWrapper<P5>(),v,index + 4),
				Get(TypeWrapper<P6>(),v,index + 5),
				Get(TypeWrapper<P7>(),v,index + 6),
				Get(TypeWrapper<P8>(),v,index + 7)
				);
			return 0;
		}
		template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8,typename P9>
		static int Call(void (*func)(P1,P2,P3,P4,P5,P6,P7,P8,P9),HSQUIRRELVM v,int index) {
			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3),
				Get(TypeWrapper<P5>(),v,index + 4),
				Get(TypeWrapper<P6>(),v,index + 5),
				Get(TypeWrapper<P7>(),v,index + 6),
				Get(TypeWrapper<P8>(),v,index + 7),
				Get(TypeWrapper<P9>(),v,index + 8)
				);
			return 0;
		}
		template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8,typename P9>
		static int Call(void (__stdcall*func)(P1,P2,P3,P4,P5,P6,P7,P8,P9),HSQUIRRELVM v,int index) {
			func(
				Get(TypeWrapper<P1>(),v,index + 0),
				Get(TypeWrapper<P2>(),v,index + 1),
				Get(TypeWrapper<P3>(),v,index + 2),
				Get(TypeWrapper<P4>(),v,index + 3),
				Get(TypeWrapper<P5>(),v,index + 4),
				Get(TypeWrapper<P6>(),v,index + 5),
				Get(TypeWrapper<P7>(),v,index + 6),
				Get(TypeWrapper<P8>(),v,index + 7),
				Get(TypeWrapper<P9>(),v,index + 8)
				);
			return 0;
		}
};
template<typename RT>
int Call(RT (*func)(),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT>
int Call(RT (__stdcall*func)(),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1>
int Call(RT (*func)(P1),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1>
int Call(RT (__stdcall*func)(P1),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2>
int Call(RT (*func)(P1,P2),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2>
int Call(RT (__stdcall*func)(P1,P2),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3>
int Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3>
int Call(RT (__stdcall*func)(P1,P2,P3),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4>
int Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4>
int Call(RT (__stdcall*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
int Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
int Call(RT (__stdcall*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}

template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
int Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
int Call(RT (__stdcall*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
int Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
int Call(RT (__stdcall*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8>
int Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7,P8),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8>
int Call(RT (__stdcall*func)(P1,P2,P3,P4,P5,P6,P7,P8),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8,typename P9>
int Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7,P8,P9),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}

template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8,typename P9>
int Call(RT (__stdcall*func)(P1,P2,P3,P4,P5,P6,P7,P8,P9),HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(func,v,index);
}


#define SQPLUS_CALL_MFUNC_RET1
#ifdef SQPLUS_CALL_MFUNC_RET1
#define CALL_QUAL
#ifdef SQPLUS_APPLY_CONST
#define CONST_QUAL const
#else
#define CONST_QUAL 
#endif 


template<typename Callee,typename RT>
int Call(Callee & callee, RT ( Callee::*func)() , HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}

template<typename Callee,typename RT,typename P1>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}

template<typename Callee,typename RT,typename P1,typename P2>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}

template<typename Callee,typename RT,typename P1,typename P2,typename P3>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}

template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}

template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}

template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}

template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6,P7) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6,P7,P8) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8,typename P9>
int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6,P7,P8,P9) CONST_QUAL, HSQUIRRELVM v,int index) {
	return ReturnSpecialization<RT>::Call(callee,func,v,index);
}

#undef SQPLUS_CALL_MFUNC_RET1
#endif // SQPLUS_CALL_MFUNC_RET1

template<typename Func>
struct DirectCallFunction {
	static inline int Dispatch(HSQUIRRELVM v) {

		StackHandler sa(v);
		int paramCount = sa.GetParamCount();
		Func * func = (Func *)sa.GetUserData(paramCount);
		return Call(*func,v,2);
	} // Dispatch
};
template<typename Func>
inline void sq_pushdirectclosure(HSQUIRRELVM v,Func func,SQUnsignedInteger nupvalues) {
	SQUserPointer up = sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
	memcpy(up,&func,sizeof(func));
	sq_newclosure(v,DirectCallFunction<Func>::Dispatch,nupvalues+1);

} // sq_pushdirectclosure

template<typename Callee,typename Func>
class DirectCallMemberFunction {
public:
	static inline int Dispatch(HSQUIRRELVM v) {
  
		StackHandler sa(v);
		int paramCount = sa.GetParamCount();
		unsigned char * ud = (unsigned char *)sa.GetUserData(paramCount);
		return Call(**(Callee**)ud,*(Func*)(ud + sizeof(Callee*)),v,2);
	} // Dispatch
};
template<typename Callee,typename Func>
inline void sq_pushdirectclosure(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) {
	unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(Callee*)+sizeof(func));  // Also pushed on stack.
	const SQUserPointer pCallee = (SQUserPointer)&callee;
	memcpy(up,&pCallee,sizeof(Callee*));
	memcpy(up + sizeof(Callee*),&func,sizeof(func));
	sq_newclosure(v,DirectCallMemberFunction<Callee,Func>::Dispatch,nupvalues+1);

} // sq_pushdirectclosure
template<typename Func>
inline void RegisterGlobal(HSQUIRRELVM v,Func func,const SQChar * name) {
	sq_pushroottable(v);
	Register(v,func,name);
	sq_poptop(v); // Remove root table.
} // RegisterGlobal

template<typename Func>
inline void Register(HSQUIRRELVM v,Func func,const SQChar * name) {
	sq_pushstring(v,name,-1);
	sq_pushdirectclosure(v,func,0);
	sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
} // Register


template<typename Callee,typename Func>
inline void Register(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
	sq_pushstring(v,name,-1);
	sq_pushdirectclosure(v,callee,func,0);
	sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
} // Register
template<typename Callee,typename Func>
inline void RegisterGlobal(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
	sq_pushroottable(v);
	Register(v,callee,func,name);
	sq_poptop(v); // Remove root table.
} // RegisterGlobal



template<typename TYPE>
void RegisterGlobalConstant(HSQUIRRELVM v,TYPE  val,SQChar* name)
{
	sq_pushstring(v,name,-1);
	v->Push(val);
	sq_createslot(v,-3);
}
template<>
void RegisterGlobalConstant(HSQUIRRELVM v,const SQChar* str,SQChar* name)
{
	sq_pushstring(v,name,-1);
	sq_pushstring(v,str,strlen(str));
	sq_createslot(v,-3);
}
template<>
void RegisterGlobalConstant(HSQUIRRELVM v,SQChar* str,SQChar* name)
{
	sq_pushstring(v,name,-1);
	sq_pushstring(v,str,strlen(str));
	sq_createslot(v,-3);
}
#endif // !defined(AFX_SQFUNCTION_H__0A8840CC_3632_4286_B67D_C4767C7269E3__INCLUDED_)
